home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Modules / posixmodule.c < prev    next >
Text File  |  1996-02-14  |  30KB  |  1,553 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* POSIX module implementation */
  26.  
  27. /* This file is also used for Windows NT.  In that case the module
  28.    actually calls itself 'nt', not 'posix', and a few functions are
  29.    either unimplemented or implemented differently.  The source
  30.    assumes that for Windows NT, the macro 'NT' is defined independent
  31.    of the compiler used.  Different compilers define their own feature
  32.    test macro, e.g. '__BORLANDC__' or '_MSCVER'. */
  33.  
  34. /* For MS-DOS and Windows 3.x, use ../Dos/dosmodule.c */
  35.  
  36. #include "allobjects.h"
  37. #include "modsupport.h"
  38. #include "ceval.h"
  39.  
  40. #include <string.h>
  41. #include <errno.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #ifdef HAVE_SYS_WAIT_H
  45. #include <sys/wait.h>        /* For WNOHANG */
  46. #endif
  47.  
  48. #include "mytime.h"        /* For clock_t on some systems */
  49.  
  50. #ifdef HAVE_FCNTL_H
  51. #include <fcntl.h>
  52. #endif /* HAVE_FCNTL_H */
  53.  
  54. #ifndef NT
  55. #define HAVE_FORK    1
  56. #endif
  57.  
  58. #if !defined(NT) || defined(__BORLANDC__)
  59. /* Unix functions that the configure script doesn't check for
  60.    and that aren't easily available under NT except with Borland C */
  61. #define HAVE_GETEGID    1
  62. #define HAVE_GETEUID    1
  63. #define HAVE_GETGID    1
  64. #define HAVE_GETPPID    1
  65. #define HAVE_GETUID    1
  66. #define HAVE_KILL    1
  67. #define HAVE_WAIT    1
  68. #define HAVE_OPENDIR    1
  69. #define HAVE_PIPE    1
  70. #define HAVE_GETCWD    1
  71. #endif
  72.  
  73. #ifndef NT
  74.  
  75. #ifdef HAVE_UNISTD_H
  76. #include <unistd.h>
  77. #endif
  78.  
  79. #ifdef NeXT
  80. /* NeXT's <unistd.h> and <utime.h> aren't worth much */
  81. #undef HAVE_UNISTD_H
  82. #undef HAVE_UTIME_H
  83. /* #undef HAVE_GETCWD */
  84. #endif
  85.  
  86. #ifdef HAVE_UNISTD_H
  87. /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
  88. extern int rename();
  89. extern int pclose();
  90. extern int lstat();
  91. extern int symlink();
  92. #else /* !HAVE_UNISTD_H */
  93. extern int mkdir PROTO((const char *, mode_t));
  94. extern int chdir PROTO((const char *));
  95. extern int rmdir PROTO((const char *));
  96. extern int chmod PROTO((const char *, mode_t));
  97. extern int chown PROTO((const char *, uid_t, gid_t));
  98. extern char *getcwd PROTO((char *, int));
  99. extern char *strerror PROTO((int));
  100. extern int link PROTO((const char *, const char *));
  101. extern int rename PROTO((const char *, const char *));
  102. extern int stat PROTO((const char *, struct stat *));
  103. extern int unlink PROTO((const char *));
  104. extern int pclose PROTO((FILE *));
  105. #ifdef HAVE_SYMLINK
  106. extern int symlink PROTO((const char *, const char *));
  107. #endif /* HAVE_SYMLINK */
  108. #ifdef HAVE_LSTAT
  109. extern int lstat PROTO((const char *, struct stat *));
  110. #endif /* HAVE_LSTAT */
  111. #endif /* !HAVE_UNISTD_H */
  112.  
  113. #endif /* !NT */
  114.  
  115. #ifdef HAVE_UTIME_H
  116. #include <utime.h>
  117. #endif /* HAVE_UTIME_H */
  118.  
  119. #ifdef HAVE_SYS_UTIME_H
  120. #include <sys/utime.h>
  121. #define HAVE_UTIME_H /* pretend we do for the rest of this file */
  122. #endif /* HAVE_SYS_UTIME_H */
  123.  
  124. #ifdef HAVE_SYS_TIMES_H
  125. #include <sys/times.h>
  126. #endif /* HAVE_SYS_TIMES_H */
  127.  
  128. #ifdef HAVE_SYS_PARAM_H
  129. #include <sys/param.h>
  130. #endif /* HAVE_SYS_PARAM_H */
  131.  
  132. #ifdef HAVE_SYS_UTSNAME_H
  133. #include <sys/utsname.h>
  134. #endif /* HAVE_SYS_UTSNAME_H */
  135.  
  136. #ifndef MAXPATHLEN
  137. #define MAXPATHLEN 1024
  138. #endif /* MAXPATHLEN */
  139.  
  140. #ifdef HAVE_DIRENT_H
  141. #include <dirent.h>
  142. #define NAMLEN(dirent) strlen((dirent)->d_name)
  143. #else
  144. #define dirent direct
  145. #define NAMLEN(dirent) (dirent)->d_namlen
  146. #ifdef HAVE_SYS_NDIR_H
  147. #include <sys/ndir.h>
  148. #endif
  149. #ifdef HAVE_SYS_DIR_H
  150. #include <sys/dir.h>
  151. #endif
  152. #ifdef HAVE_NDIR_H
  153. #include <ndir.h>
  154. #endif
  155. #endif
  156.  
  157. #ifdef NT
  158. #include <direct.h>
  159. #include <io.h>
  160. #include <process.h>
  161. #include <windows.h>
  162. #define popen   _popen
  163. #define pclose    _pclose
  164. #endif /* NT */
  165.  
  166. #ifdef OS2
  167. #include <io.h>
  168. #endif /* OS2 */
  169.  
  170. /* Return a dictionary corresponding to the POSIX environment table */
  171.  
  172. #ifndef NT
  173. extern char **environ;
  174. #endif /* !NT */
  175.  
  176. static object *
  177. convertenviron()
  178. {
  179.     object *d;
  180.     char **e;
  181.     d = newdictobject();
  182.     if (d == NULL)
  183.         return NULL;
  184.     if (environ == NULL)
  185.         return d;
  186.     /* XXX This part ignores errors */
  187.     for (e = environ; *e != NULL; e++) {
  188.         object *v;
  189.         char *p = strchr(*e, '=');
  190.         if (p == NULL)
  191.             continue;
  192.         v = newstringobject(p+1);
  193.         if (v == NULL)
  194.             continue;
  195.         *p = '\0';
  196.         (void) dictinsert(d, *e, v);
  197.         *p = '=';
  198.         DECREF(v);
  199.     }
  200.     return d;
  201. }
  202.  
  203.  
  204. static object *PosixError; /* Exception posix.error */
  205.  
  206. /* Set a POSIX-specific error from errno, and return NULL */
  207.  
  208. static object * posix_error()
  209. {
  210.     return err_errno(PosixError);
  211. }
  212.  
  213.  
  214. /* POSIX generic methods */
  215.  
  216. static object *
  217. posix_1str(args, func)
  218.     object *args;
  219.     int (*func) FPROTO((const char *));
  220. {
  221.     char *path1;
  222.     int res;
  223.     if (!getargs(args, "s", &path1))
  224.         return NULL;
  225.     BGN_SAVE
  226.     res = (*func)(path1);
  227.     END_SAVE
  228.     if (res < 0)
  229.         return posix_error();
  230.     INCREF(None);
  231.     return None;
  232. }
  233.  
  234. static object *
  235. posix_2str(args, func)
  236.     object *args;
  237.     int (*func) FPROTO((const char *, const char *));
  238. {
  239.     char *path1, *path2;
  240.     int res;
  241.     if (!getargs(args, "(ss)", &path1, &path2))
  242.         return NULL;
  243.     BGN_SAVE
  244.     res = (*func)(path1, path2);
  245.     END_SAVE
  246.     if (res < 0)
  247.         return posix_error();
  248.     INCREF(None);
  249.     return None;
  250. }
  251.  
  252. static object *
  253. posix_strint(args, func)
  254.     object *args;
  255.     int (*func) FPROTO((const char *, int));
  256. {
  257.     char *path;
  258.     int i;
  259.     int res;
  260.     if (!getargs(args, "(si)", &path, &i))
  261.         return NULL;
  262.     BGN_SAVE
  263.     res = (*func)(path, i);
  264.     END_SAVE
  265.     if (res < 0)
  266.         return posix_error();
  267.     INCREF(None);
  268.     return None;
  269. }
  270.  
  271. static object *
  272. posix_strintint(args, func)
  273.     object *args;
  274.     int (*func) FPROTO((const char *, int, int));
  275. {
  276.     char *path;
  277.     int i,i2;
  278.     int res;
  279.     if (!getargs(args, "(sii)", &path, &i, &i2))
  280.         return NULL;
  281.     BGN_SAVE
  282.     res = (*func)(path, i, i2);
  283.     END_SAVE
  284.     if (res < 0)
  285.         return posix_error();
  286.     INCREF(None);
  287.     return None;
  288. }
  289.  
  290. static object *
  291. posix_do_stat(self, args, statfunc)
  292.     object *self;
  293.     object *args;
  294.     int (*statfunc) FPROTO((const char *, struct stat *));
  295. {
  296.     struct stat st;
  297.     char *path;
  298.     int res;
  299.     if (!getargs(args, "s", &path))
  300.         return NULL;
  301.     BGN_SAVE
  302.     res = (*statfunc)(path, &st);
  303.     END_SAVE
  304.     if (res != 0)
  305.         return posix_error();
  306.     return mkvalue("(llllllllll)",
  307.             (long)st.st_mode,
  308.             (long)st.st_ino,
  309.             (long)st.st_dev,
  310.             (long)st.st_nlink,
  311.             (long)st.st_uid,
  312.             (long)st.st_gid,
  313.             (long)st.st_size,
  314.             (long)st.st_atime,
  315.             (long)st.st_mtime,
  316.             (long)st.st_ctime);
  317. }
  318.  
  319.  
  320. /* POSIX methods */
  321.  
  322. static object *
  323. posix_chdir(self, args)
  324.     object *self;
  325.     object *args;
  326. {
  327.     return posix_1str(args, chdir);
  328. }
  329.  
  330. static object *
  331. posix_chmod(self, args)
  332.     object *self;
  333.     object *args;
  334. {
  335.     return posix_strint(args, chmod);
  336. }
  337.  
  338. #ifdef HAVE_CHOWN
  339. static object *
  340. posix_chown(self, args)
  341.     object *self;
  342.     object *args;
  343. {
  344.     return posix_strintint(args, chown);
  345. }
  346. #endif /* HAVE_CHOWN */
  347.  
  348. #ifdef HAVE_GETCWD
  349. static object *
  350. posix_getcwd(self, args)
  351.     object *self;
  352.     object *args;
  353. {
  354.     char buf[1026];
  355.     char *res;
  356.     if (!getnoarg(args))
  357.         return NULL;
  358.     BGN_SAVE
  359.     res = getcwd(buf, sizeof buf);
  360.     END_SAVE
  361.     if (res == NULL)
  362.         return posix_error();
  363.     return newstringobject(buf);
  364. }
  365. #endif
  366.  
  367. #ifdef HAVE_LINK
  368. static object *
  369. posix_link(self, args)
  370.     object *self;
  371.     object *args;
  372. {
  373.     return posix_2str(args, link);
  374. }
  375. #endif /* HAVE_LINK */
  376.  
  377. static object *
  378. posix_listdir(self, args)
  379.     object *self;
  380.     object *args;
  381. {
  382. #if defined(NT) && !defined(HAVE_OPENDIR)
  383.  
  384.     char *name;
  385.     int len;
  386.     object *d, *v;
  387.     HANDLE hFindFile;
  388.     WIN32_FIND_DATA FileData;
  389.     char namebuf[MAX_PATH+5];
  390.  
  391.     if (!getargs(args, "s#", &name, &len))
  392.         return NULL;
  393.     if (len >= MAX_PATH) {
  394.         err_setstr(ValueError, "path too long");
  395.         return NULL;
  396.     }
  397.     strcpy(namebuf, name);
  398.     if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
  399.         namebuf[len++] = '/';
  400.     strcpy(namebuf + len, "*.*");
  401.  
  402.     if ((d = newlistobject(0)) == NULL)
  403.         return NULL;
  404.  
  405.     hFindFile = FindFirstFile(namebuf, &FileData);
  406.     if (hFindFile == INVALID_HANDLE_VALUE) {
  407.         errno = GetLastError();
  408.         return posix_error();
  409.     }
  410.     do {
  411.         if (FileData.cFileName[0] == '.' &&
  412.             (FileData.cFileName[1] == '\0' ||
  413.              FileData.cFileName[1] == '.' &&
  414.              FileData.cFileName[2] == '\0'))
  415.             continue;
  416.         v = newstringobject(FileData.cFileName);
  417.         if (v == NULL) {
  418.             DECREF(d);
  419.             d = NULL;
  420.             break;
  421.         }
  422.         if (addlistitem(d, v) != 0) {
  423.             DECREF(v);
  424.             DECREF(d);
  425.             d = NULL;
  426.             break;
  427.         }
  428.         DECREF(v);
  429.     } while (FindNextFile(hFindFile, &FileData) == TRUE);
  430.  
  431.     if (FindClose(hFindFile) == FALSE) {
  432.         errno = GetLastError();
  433.         return posix_error();
  434.     }
  435.  
  436.     return d;
  437.  
  438. #else /* !NT */
  439.  
  440.     char *name;
  441.     object *d, *v;
  442.     DIR *dirp;
  443.     struct dirent *ep;
  444.     if (!getargs(args, "s", &name))
  445.         return NULL;
  446.     BGN_SAVE
  447.     if ((dirp = opendir(name)) == NULL) {
  448.         RET_SAVE
  449.         return posix_error();
  450.     }
  451.     if ((d = newlistobject(0)) == NULL) {
  452.         closedir(dirp);
  453.         RET_SAVE
  454.         return NULL;
  455.     }
  456.     while ((ep = readdir(dirp)) != NULL) {
  457.         if (ep->d_name[0] == '.' &&
  458.             (NAMLEN(ep) == 1 ||
  459.              ep->d_name[1] == '.' && NAMLEN(ep) == 2))
  460.             continue;
  461.         v = newsizedstringobject(ep->d_name, NAMLEN(ep));
  462.         if (v == NULL) {
  463.             DECREF(d);
  464.             d = NULL;
  465.             break;
  466.         }
  467.         if (addlistitem(d, v) != 0) {
  468.             DECREF(v);
  469.             DECREF(d);
  470.             d = NULL;
  471.             break;
  472.         }
  473.         DECREF(v);
  474.     }
  475.     closedir(dirp);
  476.     END_SAVE
  477.  
  478.     return d;
  479.  
  480. #endif /* !NT */
  481. }
  482.  
  483. static object *
  484. posix_mkdir(self, args)
  485.     object *self;
  486.     object *args;
  487. {
  488.     return posix_strint(args, mkdir);
  489. }
  490.  
  491. #ifdef HAVE_NICE
  492. static object *
  493. posix_nice(self, args)
  494.     object *self;
  495.     object *args;
  496. {
  497.     int increment, value;
  498.  
  499.     if (!getargs(args, "i", &increment))
  500.         return NULL;
  501.     value = nice(increment);
  502.     if (value == -1)
  503.         return posix_error();
  504.     return newintobject((long) value);
  505. }
  506. #endif /* HAVE_NICE */
  507.  
  508. static object *
  509. posix_rename(self, args)
  510.     object *self;
  511.     object *args;
  512. {
  513.     return posix_2str(args, rename);
  514. }
  515.  
  516. static object *
  517. posix_rmdir(self, args)
  518.     object *self;
  519.     object *args;
  520. {
  521.     return posix_1str(args, rmdir);
  522. }
  523.  
  524. static object *
  525. posix_stat(self, args)
  526.     object *self;
  527.     object *args;
  528. {
  529.     return posix_do_stat(self, args, stat);
  530. }
  531.  
  532. static object *
  533. posix_system(self, args)
  534.     object *self;
  535.     object *args;
  536. {
  537.     char *command;
  538.     long sts;
  539.     if (!getargs(args, "s", &command))
  540.         return NULL;
  541.     BGN_SAVE
  542.     sts = system(command);
  543.     END_SAVE
  544.     return newintobject(sts);
  545. }
  546.  
  547. static object *
  548. posix_umask(self, args)
  549.     object *self;
  550.     object *args;
  551. {
  552.     int i;
  553.     if (!getintarg(args, &i))
  554.         return NULL;
  555.     i = umask(i);
  556.     if (i < 0)
  557.         return posix_error();
  558.     return newintobject((long)i);
  559. }
  560.  
  561. static object *
  562. posix_unlink(self, args)
  563.     object *self;
  564.     object *args;
  565. {
  566.     return posix_1str(args, unlink);
  567. }
  568.  
  569. #ifdef HAVE_UNAME
  570. static object *
  571. posix_uname(self, args)
  572.     object *self;
  573.     object *args;
  574. {
  575.     struct utsname u;
  576.     object *v;
  577.     int res;
  578.     if (!getnoarg(args))
  579.         return NULL;
  580.     BGN_SAVE
  581.     res = uname(&u);
  582.     END_SAVE
  583.     if (res < 0)
  584.         return posix_error();
  585.     return mkvalue("(sssss)",
  586.                u.sysname,
  587.                u.nodename,
  588.                u.release,
  589.                u.version,
  590.                u.machine);
  591. }
  592. #endif /* HAVE_UNAME */
  593.  
  594. static object *
  595. posix_utime(self, args)
  596.     object *self;
  597.     object *args;
  598. {
  599.     char *path;
  600.     long atime, mtime;
  601.     int res;
  602.  
  603. #ifdef HAVE_UTIME_H
  604.     struct utimbuf buf;
  605. #define ATIME buf.actime
  606. #define MTIME buf.modtime
  607. #define UTIME_ARG &buf
  608. #else /* HAVE_UTIME_H */
  609.     time_t buf[2];
  610. #define ATIME buf[0]
  611. #define MTIME buf[1]
  612. #define UTIME_ARG buf
  613. #endif /* HAVE_UTIME_H */
  614.  
  615.     if (!getargs(args, "(s(ll))", &path, &atime, &mtime))
  616.         return NULL;
  617.     ATIME = atime;
  618.     MTIME = mtime;
  619.     BGN_SAVE
  620.     res = utime(path, UTIME_ARG);
  621.     END_SAVE
  622.     if (res < 0)
  623.         return posix_error();
  624.     INCREF(None);
  625.     return None;
  626. #undef UTIME_ARG
  627. #undef ATIME
  628. #undef MTIME
  629. }
  630.  
  631.  
  632. /* Process operations */
  633.  
  634. static object *
  635. posix__exit(self, args)
  636.     object *self;
  637.     object *args;
  638. {
  639.     int sts;
  640.     if (!getintarg(args, &sts))
  641.         return NULL;
  642.     _exit(sts);
  643.     /* NOTREACHED */
  644. }
  645.  
  646. static object *
  647. posix_execv(self, args)
  648.     object *self;
  649.     object *args;
  650. {
  651.     char *path;
  652.     object *argv;
  653.     char **argvlist;
  654.     int i, argc;
  655.     object *(*getitem) PROTO((object *, int));
  656.  
  657.     /* execv has two arguments: (path, argv), where
  658.        argv is a list or tuple of strings. */
  659.  
  660.     if (!getargs(args, "(sO)", &path, &argv))
  661.         return NULL;
  662.     if (is_listobject(argv)) {
  663.         argc = getlistsize(argv);
  664.         getitem = getlistitem;
  665.     }
  666.     else if (is_tupleobject(argv)) {
  667.         argc = gettuplesize(argv);
  668.         getitem = gettupleitem;
  669.     }
  670.     else {
  671.  badarg:
  672.         err_badarg();
  673.         return NULL;
  674.     }
  675.  
  676.     argvlist = NEW(char *, argc+1);
  677.     if (argvlist == NULL)
  678.         return NULL;
  679.     for (i = 0; i < argc; i++) {
  680.         if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
  681.             DEL(argvlist);
  682.             goto badarg;
  683.         }
  684.     }
  685.     argvlist[argc] = NULL;
  686.  
  687. #ifdef BAD_EXEC_PROTOTYPES
  688.     execv(path, (const char **) argvlist);
  689. #else /* BAD_EXEC_PROTOTYPES */
  690.     execv(path, argvlist);
  691. #endif /* BAD_EXEC_PROTOTYPES */
  692.  
  693.     /* If we get here it's definitely an error */
  694.  
  695.     DEL(argvlist);
  696.     return posix_error();
  697. }
  698.  
  699. static object *
  700. posix_execve(self, args)
  701.     object *self;
  702.     object *args;
  703. {
  704.     char *path;
  705.     object *argv, *env;
  706.     char **argvlist;
  707.     char **envlist;
  708.     object *key, *val;
  709.     int i, pos, argc, envc;
  710.     object *(*getitem) PROTO((object *, int));
  711.  
  712.     /* execve has three arguments: (path, argv, env), where
  713.        argv is a list or tuple of strings and env is a dictionary
  714.        like posix.environ. */
  715.  
  716.     if (!getargs(args, "(sOO)", &path, &argv, &env))
  717.         return NULL;
  718.     if (is_listobject(argv)) {
  719.         argc = getlistsize(argv);
  720.         getitem = getlistitem;
  721.     }
  722.     else if (is_tupleobject(argv)) {
  723.         argc = gettuplesize(argv);
  724.         getitem = gettupleitem;
  725.     }
  726.     else {
  727.         err_setstr(TypeError, "argv must be tuple or list");
  728.         return NULL;
  729.     }
  730.     if (!is_dictobject(env)) {
  731.         err_setstr(TypeError, "env must be dictionary");
  732.         return NULL;
  733.     }
  734.  
  735.     argvlist = NEW(char *, argc+1);
  736.     if (argvlist == NULL) {
  737.         err_nomem();
  738.         return NULL;
  739.     }
  740.     for (i = 0; i < argc; i++) {
  741.         if (!getargs((*getitem)(argv, i),
  742.                  "s;argv must be list of strings",
  743.                  &argvlist[i])) {
  744.             goto fail_1;
  745.         }
  746.     }
  747.     argvlist[argc] = NULL;
  748.  
  749.     i = getmappingsize(env);
  750.     envlist = NEW(char *, i + 1);
  751.     if (envlist == NULL) {
  752.         err_nomem();
  753.         goto fail_1;
  754.     }
  755.     pos = 0;
  756.     envc = 0;
  757.     while (mappinggetnext(env, &pos, &key, &val)) {
  758.         char *p, *k, *v;
  759.         if (!getargs(key, "s;non-string key in env", &k) ||
  760.             !getargs(val, "s;non-string value in env", &v)) {
  761.             goto fail_2;
  762.         }
  763.         p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
  764.         if (p == NULL) {
  765.             err_nomem();
  766.             goto fail_2;
  767.         }
  768.         sprintf(p, "%s=%s", k, v);
  769.         envlist[envc++] = p;
  770.     }
  771.     envlist[envc] = 0;
  772.  
  773.  
  774. #ifdef BAD_EXEC_PROTOTYPES
  775.     execve(path, (const char **)argvlist, envlist);
  776. #else /* BAD_EXEC_PROTOTYPES */
  777.     execve(path, argvlist, envlist);
  778. #endif /* BAD_EXEC_PROTOTYPES */
  779.     
  780.     /* If we get here it's definitely an error */
  781.  
  782.     (void) posix_error();
  783.  
  784.  fail_2:
  785.     while (--envc >= 0)
  786.         DEL(envlist[envc]);
  787.     DEL(envlist);
  788.  fail_1:
  789.     DEL(argvlist);
  790.  
  791.     return NULL;
  792. }
  793.  
  794. #ifdef HAVE_FORK
  795. static object *
  796. posix_fork(self, args)
  797.     object *self;
  798.     object *args;
  799. {
  800.     int pid;
  801.     if (!getnoarg(args))
  802.         return NULL;
  803.     pid = fork();
  804.     if (pid == -1)
  805.         return posix_error();
  806.     return newintobject((long)pid);
  807. }
  808. #endif
  809.  
  810. #ifdef HAVE_GETEGID
  811. static object *
  812. posix_getegid(self, args)
  813.     object *self;
  814.     object *args;
  815. {
  816.     if (!getnoarg(args))
  817.         return NULL;
  818.     return newintobject((long)getegid());
  819. }
  820. #endif
  821.  
  822. #ifdef HAVE_GETEUID
  823. static object *
  824. posix_geteuid(self, args)
  825.     object *self;
  826.     object *args;
  827. {
  828.     if (!getnoarg(args))
  829.         return NULL;
  830.     return newintobject((long)geteuid());
  831. }
  832. #endif
  833.  
  834. #ifdef HAVE_GETGID
  835. static object *
  836. posix_getgid(self, args)
  837.     object *self;
  838.     object *args;
  839. {
  840.     if (!getnoarg(args))
  841.         return NULL;
  842.     return newintobject((long)getgid());
  843. }
  844. #endif
  845.  
  846. static object *
  847. posix_getpid(self, args)
  848.     object *self;
  849.     object *args;
  850. {
  851.     if (!getnoarg(args))
  852.         return NULL;
  853.     return newintobject((long)getpid());
  854. }
  855.  
  856. #ifdef HAVE_GETPGRP
  857. static object *
  858. posix_getpgrp(self, args)
  859.     object *self;
  860.     object *args;
  861. {
  862.     if (!getnoarg(args))
  863.         return NULL;
  864. #ifdef GETPGRP_HAVE_ARG
  865.     return newintobject((long)getpgrp(0));
  866. #else /* GETPGRP_HAVE_ARG */
  867.     return newintobject((long)getpgrp());
  868. #endif /* GETPGRP_HAVE_ARG */
  869. }
  870. #endif /* HAVE_GETPGRP */
  871.  
  872. #ifdef HAVE_SETPGRP
  873. static object *
  874. posix_setpgrp(self, args)
  875.     object *self;
  876.     object *args;
  877. {
  878.     if (!getnoarg(args))
  879.         return NULL;
  880. #ifdef SETPGRP_HAVE_ARG
  881.     if (setpgrp(0, 0) < 0)
  882. #else /* SETPGRP_HAVE_ARG */
  883.     if (setpgrp() < 0)
  884. #endif /* SETPGRP_HAVE_ARG */
  885.         return posix_error();
  886.     INCREF(None);
  887.     return None;
  888. }
  889.  
  890. #endif /* HAVE_SETPGRP */
  891.  
  892. #ifdef HAVE_GETPPID
  893. static object *
  894. posix_getppid(self, args)
  895.     object *self;
  896.     object *args;
  897. {
  898.     if (!getnoarg(args))
  899.         return NULL;
  900.     return newintobject((long)getppid());
  901. }
  902. #endif
  903.  
  904. #ifdef HAVE_GETUID
  905. static object *
  906. posix_getuid(self, args)
  907.     object *self;
  908.     object *args;
  909. {
  910.     if (!getnoarg(args))
  911.         return NULL;
  912.     return newintobject((long)getuid());
  913. }
  914. #endif
  915.  
  916. #ifdef HAVE_KILL
  917. static object *
  918. posix_kill(self, args)
  919.     object *self;
  920.     object *args;
  921. {
  922.     int pid, sig;
  923.     if (!getargs(args, "(ii)", &pid, &sig))
  924.         return NULL;
  925.     if (kill(pid, sig) == -1)
  926.         return posix_error();
  927.     INCREF(None);
  928.     return None;
  929. }
  930. #endif
  931.  
  932. static object *
  933. posix_popen(self, args)
  934.     object *self;
  935.     object *args;
  936. {
  937.     char *name;
  938.     char *mode = "r";
  939.     int bufsize = -1;
  940.     FILE *fp;
  941.     object *f;
  942.     if (!newgetargs(args, "s|si", &name, &mode, &bufsize))
  943.         return NULL;
  944.     BGN_SAVE
  945.     fp = popen(name, mode);
  946.     END_SAVE
  947.     if (fp == NULL)
  948.         return posix_error();
  949.     f = newopenfileobject(fp, name, mode, pclose);
  950.     if (f != NULL)
  951.         setfilebufsize(f, bufsize);
  952.     return f;
  953. }
  954.  
  955. #ifdef HAVE_SETUID
  956. static object *
  957. posix_setuid(self, args)
  958.     object *self;
  959.     object *args;
  960. {
  961.     int uid;
  962.     if (!getargs(args, "i", &uid))
  963.         return NULL;
  964.     if (setuid(uid) < 0)
  965.         return posix_error();
  966.     INCREF(None);
  967.     return None;
  968. }
  969. #endif /* HAVE_SETUID */
  970.  
  971. #ifdef HAVE_SETGID
  972. static object *
  973. posix_setgid(self, args)
  974.     object *self;
  975.     object *args;
  976. {
  977.     int gid;
  978.     if (!getargs(args, "i", &gid))
  979.         return NULL;
  980.     if (setgid(gid) < 0)
  981.         return posix_error();
  982.     INCREF(None);
  983.     return None;
  984. }
  985. #endif /* HAVE_SETGID */
  986.  
  987. #ifdef HAVE_WAITPID
  988. static object *
  989. posix_waitpid(self, args)
  990.     object *self;
  991.     object *args;
  992. {
  993.     int pid, options, sts;
  994.     if (!getargs(args, "(ii)", &pid, &options))
  995.         return NULL;
  996.     BGN_SAVE
  997.     pid = waitpid(pid, &sts, options);
  998.     END_SAVE
  999.     if (pid == -1)
  1000.         return posix_error();
  1001.     else
  1002.         return mkvalue("ii", pid, sts);
  1003. }
  1004. #endif /* HAVE_WAITPID */
  1005.  
  1006. #ifdef HAVE_WAIT
  1007. static object *
  1008. posix_wait(self, args)
  1009.     object *self;
  1010.     object *args;
  1011. {
  1012.     int pid, sts;
  1013.     BGN_SAVE
  1014.     pid = wait(&sts);
  1015.     END_SAVE
  1016.     if (pid == -1)
  1017.         return posix_error();
  1018.     else
  1019.         return mkvalue("ii", pid, sts);
  1020. }
  1021. #endif
  1022.  
  1023. static object *
  1024. posix_lstat(self, args)
  1025.     object *self;
  1026.     object *args;
  1027. {
  1028. #ifdef HAVE_LSTAT
  1029.     return posix_do_stat(self, args, lstat);
  1030. #else /* !HAVE_LSTAT */
  1031.     return posix_do_stat(self, args, stat);
  1032. #endif /* !HAVE_LSTAT */
  1033. }
  1034.  
  1035. #ifdef HAVE_READLINK
  1036. static object *
  1037. posix_readlink(self, args)
  1038.     object *self;
  1039.     object *args;
  1040. {
  1041.     char buf[MAXPATHLEN];
  1042.     char *path;
  1043.     int n;
  1044.     if (!getargs(args, "s", &path))
  1045.         return NULL;
  1046.     BGN_SAVE
  1047.     n = readlink(path, buf, (int) sizeof buf);
  1048.     END_SAVE
  1049.     if (n < 0)
  1050.         return posix_error();
  1051.     return newsizedstringobject(buf, n);
  1052. }
  1053. #endif /* HAVE_READLINK */
  1054.  
  1055. #ifdef HAVE_SYMLINK
  1056. static object *
  1057. posix_symlink(self, args)
  1058.     object *self;
  1059.     object *args;
  1060. {
  1061.     return posix_2str(args, symlink);
  1062. }
  1063. #endif /* HAVE_SYMLINK */
  1064.  
  1065. #ifdef HAVE_TIMES
  1066. #ifndef HZ
  1067. #define HZ 60 /* Universal constant :-) */
  1068. #endif /* HZ */
  1069. static object *
  1070. posix_times(self, args)
  1071.     object *self;
  1072.     object *args;
  1073. {
  1074.     struct tms t;
  1075.     clock_t c;
  1076.     if (!getnoarg(args))
  1077.         return NULL;
  1078.     errno = 0;
  1079.     c = times(&t);
  1080.     if (c == (clock_t) -1)
  1081.         return posix_error();
  1082.     return mkvalue("ddddd",
  1083.                (double)t.tms_utime / HZ,
  1084.                (double)t.tms_stime / HZ,
  1085.                (double)t.tms_cutime / HZ,
  1086.                (double)t.tms_cstime / HZ,
  1087.                (double)c / HZ);
  1088. }
  1089. #endif /* HAVE_TIMES */
  1090. #if defined(NT) && !defined(HAVE_TIMES)
  1091. #define HAVE_TIMES    /* so the method table will pick it up */
  1092. static object *
  1093. posix_times(self, args)
  1094.     object *self;
  1095.     object *args;
  1096. {
  1097.     FILETIME create, exit, kernel, user;
  1098.     HANDLE hProc;
  1099.     if (!getnoarg(args))
  1100.         return NULL;
  1101.     hProc = GetCurrentProcess();
  1102.     GetProcessTimes(hProc,&create, &exit, &kernel, &user);
  1103.     return mkvalue("ddddd",
  1104.                (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6,
  1105.                (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
  1106.                (double)0,
  1107.                (double)0,
  1108.                (double)0);
  1109. }
  1110. #endif /* NT */
  1111.  
  1112. #ifdef HAVE_SETSID
  1113. static object *
  1114. posix_setsid(self, args)
  1115.     object *self;
  1116.     object *args;
  1117. {
  1118.     if (!getnoarg(args))
  1119.         return NULL;
  1120.     if (setsid() < 0)
  1121.         return posix_error();
  1122.     INCREF(None);
  1123.     return None;
  1124. }
  1125. #endif /* HAVE_SETSID */
  1126.  
  1127. #ifdef HAVE_SETPGID
  1128. static object *
  1129. posix_setpgid(self, args)
  1130.     object *self;
  1131.     object *args;
  1132. {
  1133.     int pid, pgrp;
  1134.     if (!getargs(args, "(ii)", &pid, &pgrp))
  1135.         return NULL;
  1136.     if (setpgid(pid, pgrp) < 0)
  1137.         return posix_error();
  1138.     INCREF(None);
  1139.     return None;
  1140. }
  1141. #endif /* HAVE_SETPGID */
  1142.  
  1143. #ifdef HAVE_TCGETPGRP
  1144. static object *
  1145. posix_tcgetpgrp(self, args)
  1146.     object *self;
  1147.     object *args;
  1148. {
  1149.     int fd, pgid;
  1150.     if (!getargs(args, "i", &fd))
  1151.         return NULL;
  1152.     pgid = tcgetpgrp(fd);
  1153.     if (pgid < 0)
  1154.         return posix_error();
  1155.     return newintobject((long)pgid);
  1156. }
  1157. #endif /* HAVE_TCGETPGRP */
  1158.  
  1159. #ifdef HAVE_TCSETPGRP
  1160. static object *
  1161. posix_tcsetpgrp(self, args)
  1162.     object *self;
  1163.     object *args;
  1164. {
  1165.     int fd, pgid;
  1166.     if (!getargs(args, "(ii)", &fd, &pgid))
  1167.         return NULL;
  1168.     if (tcsetpgrp(fd, pgid) < 0)
  1169.         return posix_error();
  1170.        INCREF(None);
  1171.     return None;
  1172. }
  1173. #endif /* HAVE_TCSETPGRP */
  1174.  
  1175. /* Functions acting on file descriptors */
  1176.  
  1177. static object *
  1178. posix_open(self, args)
  1179.     object *self;
  1180.     object *args;
  1181. {
  1182.     char *file;
  1183.     int flag;
  1184.     int mode = 0777;
  1185.     int fd;
  1186.     if (!getargs(args, "(si)", &file, &flag)) {
  1187.         err_clear();
  1188.         if (!getargs(args, "(sii)", &file, &flag, &mode))
  1189.             return NULL;
  1190.     }
  1191.     BGN_SAVE
  1192.     fd = open(file, flag, mode);
  1193.     END_SAVE
  1194.     if (fd < 0)
  1195.         return posix_error();
  1196.     return newintobject((long)fd);
  1197. }
  1198.  
  1199. static object *
  1200. posix_close(self, args)
  1201.     object *self;
  1202.     object *args;
  1203. {
  1204.     int fd, res;
  1205.     if (!getargs(args, "i", &fd))
  1206.         return NULL;
  1207.     BGN_SAVE
  1208.     res = close(fd);
  1209.     END_SAVE
  1210.     if (res < 0)
  1211.         return posix_error();
  1212.     INCREF(None);
  1213.     return None;
  1214. }
  1215.  
  1216. static object *
  1217. posix_dup(self, args)
  1218.     object *self;
  1219.     object *args;
  1220. {
  1221.     int fd;
  1222.     if (!getargs(args, "i", &fd))
  1223.         return NULL;
  1224.     BGN_SAVE
  1225.     fd = dup(fd);
  1226.     END_SAVE
  1227.     if (fd < 0)
  1228.         return posix_error();
  1229.     return newintobject((long)fd);
  1230. }
  1231.  
  1232. static object *
  1233. posix_dup2(self, args)
  1234.     object *self;
  1235.     object *args;
  1236. {
  1237.     int fd, fd2, res;
  1238.     if (!getargs(args, "(ii)", &fd, &fd2))
  1239.         return NULL;
  1240.     BGN_SAVE
  1241.     res = dup2(fd, fd2);
  1242.     END_SAVE
  1243.     if (res < 0)
  1244.         return posix_error();
  1245.     INCREF(None);
  1246.     return None;
  1247. }
  1248.  
  1249. static object *
  1250. posix_lseek(self, args)
  1251.     object *self;
  1252.     object *args;
  1253. {
  1254.     int fd, how;
  1255.     long pos, res;
  1256.     if (!getargs(args, "(ili)", &fd, &pos, &how))
  1257.         return NULL;
  1258. #ifdef SEEK_SET
  1259.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  1260.     switch (how) {
  1261.     case 0: how = SEEK_SET; break;
  1262.     case 1: how = SEEK_CUR; break;
  1263.     case 2: how = SEEK_END; break;
  1264.     }
  1265. #endif /* SEEK_END */
  1266.     BGN_SAVE
  1267.     res = lseek(fd, pos, how);
  1268.     END_SAVE
  1269.     if (res < 0)
  1270.         return posix_error();
  1271.     return newintobject(res);
  1272. }
  1273.  
  1274. static object *
  1275. posix_read(self, args)
  1276.     object *self;
  1277.     object *args;
  1278. {
  1279.     int fd, size;
  1280.     object *buffer;
  1281.     if (!getargs(args, "(ii)", &fd, &size))
  1282.         return NULL;
  1283.     buffer = newsizedstringobject((char *)NULL, size);
  1284.     if (buffer == NULL)
  1285.         return NULL;
  1286.     BGN_SAVE
  1287.     size = read(fd, getstringvalue(buffer), size);
  1288.     END_SAVE
  1289.     if (size < 0) {
  1290.         DECREF(buffer);
  1291.         return posix_error();
  1292.     }
  1293.     resizestring(&buffer, size);
  1294.     return buffer;
  1295. }
  1296.  
  1297. static object *
  1298. posix_write(self, args)
  1299.     object *self;
  1300.     object *args;
  1301. {
  1302.     int fd, size;
  1303.     char *buffer;
  1304.     if (!getargs(args, "(is#)", &fd, &buffer, &size))
  1305.         return NULL;
  1306.     BGN_SAVE
  1307.     size = write(fd, buffer, size);
  1308.     END_SAVE
  1309.     if (size < 0)
  1310.         return posix_error();
  1311.     return newintobject((long)size);
  1312. }
  1313.  
  1314. static object *
  1315. posix_fstat(self, args)
  1316.     object *self;
  1317.     object *args;
  1318. {
  1319.     int fd;
  1320.     struct stat st;
  1321.     int res;
  1322.     if (!getargs(args, "i", &fd))
  1323.         return NULL;
  1324.     BGN_SAVE
  1325.     res = fstat(fd, &st);
  1326.     END_SAVE
  1327.     if (res != 0)
  1328.         return posix_error();
  1329.     return mkvalue("(llllllllll)",
  1330.             (long)st.st_mode,
  1331.             (long)st.st_ino,
  1332.             (long)st.st_dev,
  1333.             (long)st.st_nlink,
  1334.             (long)st.st_uid,
  1335.             (long)st.st_gid,
  1336.             (long)st.st_size,
  1337.             (long)st.st_atime,
  1338.             (long)st.st_mtime,
  1339.             (long)st.st_ctime);
  1340. }
  1341.  
  1342. static object *
  1343. posix_fdopen(self, args)
  1344.     object *self;
  1345.     object *args;
  1346. {
  1347.     extern int fclose PROTO((FILE *));
  1348.     int fd;
  1349.     char *mode = "r";
  1350.     int bufsize = -1;
  1351.     FILE *fp;
  1352.     object *f;
  1353.     if (!newgetargs(args, "i|si", &fd, &mode, &bufsize))
  1354.         return NULL;
  1355.     BGN_SAVE
  1356.     fp = fdopen(fd, mode);
  1357.     END_SAVE
  1358.     if (fp == NULL)
  1359.         return posix_error();
  1360.     f = newopenfileobject(fp, "(fdopen)", mode, fclose);
  1361.     if (f != NULL)
  1362.         setfilebufsize(f, bufsize);
  1363.     return f;
  1364. }
  1365.  
  1366. static object *
  1367. posix_pipe(self, args)
  1368.     object *self;
  1369.     object *args;
  1370. {
  1371. #if !defined(NT) || defined(HAVE_PIPE)
  1372.     int fds[2];
  1373.     int res;
  1374.     if (!getargs(args, ""))
  1375.         return NULL;
  1376.     BGN_SAVE
  1377.     res = pipe(fds);
  1378.     END_SAVE
  1379.     if (res != 0)
  1380.         return posix_error();
  1381.     return mkvalue("(ii)", fds[0], fds[1]);
  1382. #else /* NT */
  1383.     HANDLE read, write;
  1384.     BOOL ok;
  1385.     if (!getargs(args, ""))
  1386.         return NULL;
  1387.     BGN_SAVE
  1388.     ok = CreatePipe( &read, &write, NULL, 0);
  1389.     END_SAVE
  1390.     if (!ok)
  1391.         return posix_error();
  1392.     return mkvalue("(ii)", read, write);
  1393. #endif /* NT */
  1394. }
  1395.  
  1396. static struct methodlist posix_methods[] = {
  1397.     {"chdir",    posix_chdir},
  1398.     {"chmod",    posix_chmod},
  1399. #ifdef HAVE_CHOWN
  1400.     {"chown",    posix_chown},
  1401. #endif /* HAVE_CHOWN */
  1402. #ifdef HAVE_GETCWD
  1403.     {"getcwd",    posix_getcwd},
  1404. #endif
  1405. #ifdef HAVE_LINK
  1406.     {"link",    posix_link},
  1407. #endif /* HAVE_LINK */
  1408.     {"listdir",    posix_listdir},
  1409.     {"lstat",    posix_lstat},
  1410.     {"mkdir",    posix_mkdir},
  1411. #ifdef HAVE_NICE
  1412.     {"nice",    posix_nice},
  1413. #endif /* HAVE_NICE */
  1414. #ifdef HAVE_READLINK
  1415.     {"readlink",    posix_readlink},
  1416. #endif /* HAVE_READLINK */
  1417.     {"rename",    posix_rename},
  1418.     {"rmdir",    posix_rmdir},
  1419.     {"stat",    posix_stat},
  1420. #ifdef HAVE_SYMLINK
  1421.     {"symlink",    posix_symlink},
  1422. #endif /* HAVE_SYMLINK */
  1423.     {"system",    posix_system},
  1424.     {"umask",    posix_umask},
  1425. #ifdef HAVE_UNAME
  1426.     {"uname",    posix_uname},
  1427. #endif /* HAVE_UNAME */
  1428.     {"unlink",    posix_unlink},
  1429.     {"remove",    posix_unlink},
  1430.     {"utime",    posix_utime},
  1431. #ifdef HAVE_TIMES
  1432.     {"times",    posix_times},
  1433. #endif /* HAVE_TIMES */
  1434.     {"_exit",    posix__exit},
  1435.     {"execv",    posix_execv},
  1436.     {"execve",    posix_execve},
  1437. #ifdef HAVE_FORK
  1438.     {"fork",    posix_fork},
  1439. #endif /* HAVE_FORK */
  1440. #ifdef HAVE_GETEGID
  1441.     {"getegid",    posix_getegid},
  1442. #endif /* HAVE_GETEGID */
  1443. #ifdef HAVE_GETEUID
  1444.     {"geteuid",    posix_geteuid},
  1445. #endif /* HAVE_GETEUID */
  1446. #ifdef HAVE_GETGID
  1447.     {"getgid",    posix_getgid},
  1448. #endif /* HAVE_GETGID */
  1449.     {"getpid",    posix_getpid},
  1450. #ifdef HAVE_GETPGRP
  1451.     {"getpgrp",    posix_getpgrp},
  1452. #endif /* HAVE_GETPGRP */
  1453. #ifdef HAVE_GETPPID
  1454.     {"getppid",    posix_getppid},
  1455. #endif /* HAVE_GETPPID */
  1456. #ifdef HAVE_GETUID
  1457.     {"getuid",    posix_getuid},
  1458. #endif /* HAVE_GETUID */
  1459. #ifdef HAVE_KILL
  1460.     {"kill",    posix_kill},
  1461. #endif /* HAVE_KILL */
  1462.     {"popen",    posix_popen,    1},
  1463. #ifdef HAVE_SETUID
  1464.     {"setuid",    posix_setuid},
  1465. #endif /* HAVE_SETUID */
  1466. #ifdef HAVE_SETGID
  1467.     {"setgid",    posix_setgid},
  1468. #endif /* HAVE_SETGID */
  1469. #ifdef HAVE_SETPGRP
  1470.     {"setpgrp",    posix_setpgrp},
  1471. #endif /* HAVE_SETPGRP */
  1472. #ifdef HAVE_WAIT
  1473.     {"wait",    posix_wait},
  1474. #endif /* HAVE_WAIT */
  1475. #ifdef HAVE_WAITPID
  1476.     {"waitpid",    posix_waitpid},
  1477. #endif /* HAVE_WAITPID */
  1478. #ifdef HAVE_SETSID
  1479.     {"setsid",    posix_setsid},
  1480. #endif /* HAVE_SETSID */
  1481. #ifdef HAVE_SETPGID
  1482.     {"setpgid",    posix_setpgid},
  1483. #endif /* HAVE_SETPGID */
  1484. #ifdef HAVE_TCGETPGRP
  1485.     {"tcgetpgrp",    posix_tcgetpgrp},
  1486. #endif /* HAVE_TCGETPGRP */
  1487. #ifdef HAVE_TCSETPGRP
  1488.     {"tcsetpgrp",    posix_tcsetpgrp},
  1489. #endif /* HAVE_TCSETPGRP */
  1490.     {"open",    posix_open},
  1491.     {"close",    posix_close},
  1492.     {"dup",        posix_dup},
  1493.     {"dup2",    posix_dup2},
  1494.     {"lseek",    posix_lseek},
  1495.     {"read",    posix_read},
  1496.     {"write",    posix_write},
  1497.     {"fstat",    posix_fstat},
  1498.     {"fdopen",    posix_fdopen,    1},
  1499.     {"pipe",    posix_pipe},
  1500.     {NULL,        NULL}         /* Sentinel */
  1501. };
  1502.  
  1503.  
  1504. #ifdef NT
  1505. void
  1506. initnt()
  1507. {
  1508.     object *m, *d, *v;
  1509.     
  1510.     m = initmodule("nt", posix_methods);
  1511.     d = getmoduledict(m);
  1512.     
  1513.     /* Initialize nt.environ dictionary */
  1514.     v = convertenviron();
  1515.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1516.         fatal("can't define nt.environ");
  1517.     DECREF(v);
  1518.     
  1519.     /* Initialize nt.error exception */
  1520.     PosixError = newstringobject("nt.error");
  1521.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1522.         fatal("can't define nt.error");
  1523. }
  1524. #else /* !NT */
  1525. void
  1526. initposix()
  1527. {
  1528.     object *m, *d, *v;
  1529.     
  1530.     m = initmodule("posix", posix_methods);
  1531.     d = getmoduledict(m);
  1532.     
  1533.     /* Initialize posix.environ dictionary */
  1534.     v = convertenviron();
  1535.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1536.         fatal("can't define posix.environ");
  1537.     DECREF(v);
  1538.     
  1539. #ifdef WNOHANG
  1540.     /* Export WNOHANG symbol */
  1541.     v = newintobject((long)WNOHANG);
  1542.     if (v == NULL || dictinsert(d, "WNOHANG", v) != 0)
  1543.         fatal("can't define posix.WNOHANG");
  1544.     DECREF(v);
  1545. #endif
  1546.     
  1547.     /* Initialize posix.error exception */
  1548.     PosixError = newstringobject("posix.error");
  1549.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1550.         fatal("can't define posix.error");
  1551. }
  1552. #endif /* !NT */
  1553.